package com.example.service.collar.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.dao.CacheDao;
import com.example.dto.business.PetBusinessDTO;
import com.example.dto.business.PetPhotoBusinessDTO;
import com.example.exception.InsertException;
import com.example.exception.collar.CollarNotBindException;
import com.example.exception.db.UpdateException;
import com.example.mapper.CollarMapper;
import com.example.mapper.PetMapper;
import com.example.mapper.PetPhotoMapper;
import com.example.mapper.UserMapper;
import com.example.pojo.*;
import com.example.service.collar.CollarService;
import com.example.socket.server.SocketServer;
import com.example.socket.server.WebSocketServer;
import com.example.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author w
 */
@Service
public class CollarServiceImpl implements CollarService{
    @Autowired
    CollarMapper collarMapper;
    @Autowired
    CacheDao cacheDao;
    @Autowired
    UserMapper userMapper;
    @Autowired
    RedisTemplate<String,Object> redisTemplate;
    @Autowired
    PetMapper petMapper;
    @Autowired
    PetPhotoMapper petPhotoMapper;

    @Override
    public Integer getBindedUserId(String ip) {
        Collar collar = collarMapper.selectById(ip);
        if (collar==null||collar.getUserId()==0){
            return null;
        }else {
            return collar.getUserId();
        }
    }

    @Override
    @Transactional(rollbackFor = {InsertException.class, UpdateException.class})
    public void insertCollar(int userId, Collar collar) {
        collar.setPetId(0);
        collar.setUserId(userId);;
        int insert = collarMapper.myInsert(collar);
        if (insert!=1){
            throw new InsertException("项圈信息插入失败");
        }
        SocketServer.connectingSockets.put(collar.getCollarId(),userId);
    }

    @Override
    public List<Collar> getUserAllCollars(int userId) {
        QueryWrapper<Collar> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",userId);
        return collarMapper.selectList(queryWrapper);
    }

    @Override
    public List<CollarMsg> getHistoryCollarMsgs(String ip,String time) {
        List<CollarMsg> historyMsgs = RedisUtil.getHistoryMsgs(ip);
        List<CollarMsg> ans = new ArrayList<>();
        for (CollarMsg historyMsg : historyMsgs) {
            String time1 = historyMsg.getTime().split(" ")[0];
            if (time1.equals(time)){
                ans.add(historyMsg);
            }
        }
        return ans;
    }

    @Override
    public CollarMsg getRecentlyCollarMsg(String ip) {
        return RedisUtil.getRecentMsg(ip);
    }

    /**
     * 设置项圈获取硬件信息的频率
     *
     * @param ip   项圈ip
     * @param time 频率
     */
    @Override
    public void setCollarMsgSendFrequency(String ip, int time) {
        RedisUtil.setSleepTime(ip,time);
    }

    /**
     * 获取目前所有公开的宠物位置,请求者位置为一个数据
     *
     * @param ip 请求者ip
     * @return 所有位置信息
     */
    @Override
    public List<MapMsg> getPublicPetMap(String ip) {
        Set<String> keys = redisTemplate.keys("*?.*?.*?.*?");
        Set<String> publicCollarIp = collarMapper.getPublicCollarIp();
        assert keys != null;
        keys.retainAll(publicCollarIp);
        List<MapMsg> mapMsgs = new ArrayList<>();
        CollarMsg recentMsg1 = RedisUtil.getRecentMsg(ip);
        assert recentMsg1 != null;
        mapMsgs.add(new MapMsg(recentMsg1.getLatitude(),recentMsg1.getLongitude(),ip,recentMsg1.getTime()));
        keys.remove(ip);
        for (String key : keys) {
            CollarMsg recentMsg = RedisUtil.getRecentMsg(key);
            assert recentMsg != null;
            mapMsgs.add(new MapMsg(recentMsg.getLatitude(),recentMsg.getLongitude(),key,recentMsg.getTime()));
        }
        return mapMsgs;
    }

    /**
     * 根据项圈ip获取绑定的宠物
     *
     * @param ip 项圈ip
     * @return 宠物信息
     */
    @Override
    public PetBusinessDTO getPetByIp(String ip) {
        Collar collar = collarMapper.selectById(ip);
        if (collar==null){
            return null;
        }
        Pet queryRes = petMapper.selectById(collar.getPetId());
        if (null == queryRes) {
            throw new CollarNotBindException("该项圈还没有绑定宠物!");
        }
        PetBusinessDTO dto = new PetBusinessDTO();
        dto.setPetId(queryRes.getId());
        dto.setPetName(queryRes.getName());
        dto.setPetPortraitPath(queryRes.getPortraitPath());
        dto.setPetBreed(queryRes.getBreed());
        dto.setOvert(queryRes.getOvert());
        dto.setUserId(queryRes.getUserId());
        dto.setPetIntroduction(queryRes.getIntroduction());
        List<PetPhoto> petPhotos = petPhotoMapper.selectByPetId(queryRes.getId());
        List<PetPhotoBusinessDTO> photosDTO = new ArrayList<>();
        if (null != petPhotos) {
            for (PetPhoto petPhoto : petPhotos) {
                photosDTO.add(new PetPhotoBusinessDTO(petPhoto));
            }
        }
        dto.setPhotos(photosDTO);
        return dto;
    }

    /**
     * 绑定项圈与用户
     *
     * @param collar 项圈ip和宠物id
     * @return 是否成功
     */
    @Override
    public boolean bindCollarWithPet(Collar collar) {
        Collar collar1 = collarMapper.selectById(collar.getCollarId());
        List<Collar> petId = collarMapper.selectList(new QueryWrapper<Collar>().eq("pet_id", collar1.getPetId()).ne("pet_id",0));
        if (petId.size()>0){
            return false;
        }
        int i = collarMapper.updateById(collar);
        return i==1;
    }

    /**
     * 取消绑定项圈和用户
     *
     * @param collar petid和collarid信息
     * @return 是否成功
     */
    @Override
    public boolean cancelBind(Collar collar) {
        int i = collarMapper.deleteById(collar.getCollarId());
        WebSocketServer.onlineSessions.remove(collar.getCollarId());
        return i==1;
    }
}
